﻿using System.Collections.Generic;
using System.ComponentModel;
using Dataweb.NShape.Advanced;
using Dataweb.NShape;
using cz.zcu.PreSti.Components;
using System.Drawing;
using System;

namespace cz.zcu.PreSti.Shapes
{
    public class DiscreteGeneratorSymbol : GeneratorSymbol
    {
        #region ISymbol Members

        public override BaseComponent initializeComponent(IPresentation p)
        {
            DiscreteGeneratorModel model = (DiscreteGeneratorModel)this.ModelObject;
            DiscreteGenerator generator = new DiscreteGenerator();
            foreach (DiscreteGeneratorModel.DiscreteGeneratorPossibility pos in model.Values)
            {
                generator.Values.Add(new DiscreteGenerator.DiscreteGeneratorPossibility(pos.Probability, pos.Value));
            }
            return generator;
        }

        #endregion

        protected internal DiscreteGeneratorSymbol(ShapeType shapeType, Template template)
            : base(shapeType, template)
        {
        }


        protected internal DiscreteGeneratorSymbol(ShapeType shapeType, IStyleSet styleSet)
            : base(shapeType, styleSet)
        {
        }

        public override Shape Clone()
        {
            Shape result = new DiscreteGeneratorSymbol(Type, (Template)null);
            result.CopyFrom(this);
            return result;
        }

        public override void CopyFrom(Shape source)
        {
            base.CopyFrom(source);
        }

        protected override void DrawIcon(Graphics graphics)
        {
            graphics.DrawImage(icons.discrete, new Rectangle(X - Diameter / 2, Y - Diameter / 2, Diameter, Diameter));
        }

        internal static Shape CreateInstance(ShapeType shapeType, Template template)
        {
            return new DiscreteGeneratorSymbol(shapeType, template);
        }

    }

    public class DiscreteGeneratorModel : ModelObjectBase
    {

        #region Fields

        private List<DiscreteGeneratorPossibility> values = new List<DiscreteGeneratorPossibility>();

        private char securityDomainName = 'A';

        private const int PropertyIdValues = 1;

        #endregion

        #region properties

        [Category("Presentation")]
        [Description("List of possible values and their probabilities. Click to edit.")]
        [PropertyMappingId(PropertyIdValues)]
        [Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public virtual List<DiscreteGeneratorPossibility> Values
        {
            get
            {
                return values;
            }
            set
            {
                values = value;
            }
        }

        public class DiscreteGeneratorPossibility
        {
            private float probability = 0;
            private string val = "";

            private const int PropertyIdProbability = 1;
            private const int PropertyIdValue = 2;

            [Description("Probabilty in % of generating the assigned value. The sum of all probabilities should be 100%.")]
            [PropertyMappingId(PropertyIdProbability)]
            public float Probability
            {
                get
                {
                    return probability;
                }
                set
                {
                    probability = value;
                }
            }

            [Description("Value")]
            [PropertyMappingId(PropertyIdProbability)]
            public string Value
            {
                get
                {
                    return val;
                }
                set
                {
                    val = value;
                }
            }
        }

        #endregion

        public static DiscreteGeneratorModel CreateInstance(ModelObjectType modelObjectType)
        {
            return new DiscreteGeneratorModel(modelObjectType);
        }


        protected internal DiscreteGeneratorModel(ModelObjectType modelObjectType)
            : base(modelObjectType)
        {
            this.terminalCount = 1;
        }


        protected internal DiscreteGeneratorModel(DiscreteGeneratorModel source)
            : base(source)
        {
            Values = source.Values;
            this.terminalCount = 1;
        }


        public override IModelObject Clone()
        {
            return new DiscreteGeneratorModel(this);
        }


        public override IEnumerable<MenuItemDef> GetMenuItemDefs()
        {
            throw new NotImplementedException();
        }


        public override void Connect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
        {
        }


        public override void Disconnect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
        {
        }

        public override char SecurityDomainName
        {
            get { return securityDomainName; }
            set
            {
                if (value < 'A' || value > 'Z')
                    throw new ArgumentOutOfRangeException("SecurityDomainName", "The domain qualifier has to be an upper case  ANSI letter (A-Z).");
                securityDomainName = value;
            }
        }

        #region IEntity Members

        public static new IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions(int version)
        {
            foreach (EntityPropertyDefinition pi in ModelObjectBase.GetPropertyDefinitions(version))
                yield return pi;
            yield return new EntityFieldDefinition("Probabilities", typeof(string));
            yield return new EntityFieldDefinition("Values", typeof(string));
        }

        protected override void LoadFieldsCore(IRepositoryReader reader, int version)
        {
            int proi = 0;
            int vali = 0;
            int proi2 = 0;
            int vali2 = 0;
            base.LoadFieldsCore(reader, version);
            Values = new List<DiscreteGeneratorPossibility>();
            DiscreteGeneratorPossibility p;
            string pros = reader.ReadString();
            string vals = reader.ReadString();
            do
            {
                proi2 = pros.IndexOf("|", proi);
                vali2 = vals.IndexOf("|", vali);
                if(proi2 == 1 || vali2 == -1) break;
                p = new DiscreteGeneratorPossibility();
                p.Probability = float.Parse(pros.Substring(proi, proi2 - proi));
                p.Value = vals.Substring(vali, vali2 - vali);
                Values.Add(p);
                proi = proi2 + 1;
                vali = vali2 + 1;
            } while (pros.Length != proi2 + 1 && vals.Length != vali2 + 1);
        }

        protected override void SaveFieldsCore(IRepositoryWriter writer, int version)
        {
            string pros = "";
            string vals = "";
            base.SaveFieldsCore(writer, version);
            foreach (DiscreteGeneratorPossibility p in values)
            {
                pros += p.Probability.ToString() + "|";
                vals += p.Value + "|";
            }
            writer.WriteString(pros);
            writer.WriteString(vals);
        }

        #endregion

    }
}
